﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using Motorway_Simulator.Components;
using Motorway_Simulator.Simulator;
using System.Collections;
using Motorway_Simulator.FileIO;

namespace Motorway_Simulator.GUI.Designer
{
    /// <summary>
    /// Class which handles drawing grids and placing/removing components
    /// </summary>
    public class DesignCanvas : Panel
    {
        /// <summary>
        /// Default square unit
        /// </summary>
        public static int squareUnit = 100;

        /// <summary>
        /// Zoom level
        /// </summary>
        private float zoom;

        /// <summary>
        /// Indicates if grid needs to be drawn
        /// </summary>
        private bool gridEnabled;

        /// <summary>
        /// X size, Y size
        /// </summary>
        private int xSize, ySize;

        /// <summary>
        /// Holds the current direction of the canvas's selected road unit
        /// </summary>
        private int roadUnitOrientation;

        /// <summary>
        /// Gives direction
        /// </summary>
        private RoadUnit.Direction direction;

     

        /// <summary>
        /// Holds the road unit map
        /// </summary>
        private List<RoadUnit> roadUnitMap;

     
       


        /// <summary>
        /// Delegation for setting status label
        /// </summary>
        /// <param name="message"></param>
        public delegate void StatusLabelDelegate(string message);

        /// <summary>
        /// Method callback method
        /// </summary>
        public StatusLabelDelegate StatusLabelCallBack;

        /// <summary>
        /// Initializes a new instance of the <see cref="DesignCanvas"/> class.
        /// </summary>
        public DesignCanvas()
            : base()
        {
            // Initalize objects and default settings
            
            gridEnabled = true;

   

            // Initialize default settings
            zoom = 1F;
            xSize = 3000;
            ySize = 3000;
            this.Height = xSize;
            this.Width = xSize;

            // Default direction is NORTH
            direction = RoadUnit.Direction.NORTH;
            roadUnitMap = new List<RoadUnit>();
            this.Refresh();
        }

        /// <summary>
        /// Gets or sets a value indicating whether [grid enabled].
        /// </summary>
        /// <value><c>true</c> if [grid enabled]; otherwise, <c>false</c>.</value>
        public bool GridEnabled
        {
            get { return gridEnabled; }
            set { gridEnabled = value; }
        }

        /// <summary>
        /// Sets the zoom.
        /// </summary>
        /// <value>The zoom.</value>
        public float Zoom
        {
            set
            {
                zoom = value / 100F;
                this.Width = (int)(xSize * zoom);
                this.Height = (int)(ySize * zoom);

                updateRoadUnitZoom();


                this.AdjustFormScrollbars(true);
                this.Refresh();
            }
        }

        /// <summary>
        /// Updates the road unit zoom.
        /// </summary>
        private void updateRoadUnitZoom()
        {
            // Updates the road unit image's zoom level
            foreach (RoadUnit roadUnit in roadUnitMap)
            {
                Point p = new Point((int)((roadUnit.Position.X / roadUnit.ImageZoom) * zoom), (int)((roadUnit.Position.Y / roadUnit.ImageZoom) * zoom));
                roadUnit.ImageZoom = zoom;
                roadUnit.Position = p;
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseClick"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            this.Invalidate();
        }

        /// <summary>
        /// Sets the road unit orientation.
        /// </summary>
        /// <value>The road unit orientation.</value>
        public int RoadUnitOrientation
        {
            set
            {
                roadUnitOrientation = value;

                if (roadUnitOrientation == 0) { direction = RoadUnit.Direction.NORTH; }
                else if (roadUnitOrientation == 1) { direction = RoadUnit.Direction.EAST; }
                else if (roadUnitOrientation == 2) { direction = RoadUnit.Direction.SOUTH; }
                else if (roadUnitOrientation == 3) { direction = RoadUnit.Direction.WEST; }
     
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
           

            // If grid is enable draw grid
            if (gridEnabled)
            {
                for (int y = 0; y < ySize; y += (int)(squareUnit * zoom))
                {
                    e.Graphics.DrawLine(new Pen(Brushes.Black, 1), new Point(0, y), new Point(xSize, y));

                }
                for (int x = 0; x < xSize; x += (int)(squareUnit * zoom))
                {
                    e.Graphics.DrawLine(new Pen(Brushes.Black, 1), new Point(x, 0), new Point(x, ySize));
                }
            }

            // Draw road units
            foreach (RoadUnit roadUnit in roadUnitMap)
            {
                roadUnit.Draw(e.Graphics);
            }
        }

        /// <summary>
        /// News the orientation.
        /// </summary>
        /// <param name="roadUnitOrientation">The road unit orientation.</param>
        private void NewOrientation(int roadUnitOrientation)
        {
            this.roadUnitOrientation = roadUnitOrientation;
        }

        /// <summary>
        /// Deletes road unit from specified x, y values
        /// Do nothing when it cannot find road unit
        /// </summary>
        /// <param name="x">X position</param>
        /// <param name="y">Y position</param>
        /// <returns>True if road unit is found</returns>
        public bool DeleteRoadUnit(int x, int y)
        {
            // Formula for getting point position
            int xPosition = (int)(x - (x % (zoom * squareUnit)));
            int yPosition = (int)(y - (y % (zoom * squareUnit)));

            bool isRemoved = false;
            Point deletePoint = new Point(xPosition, yPosition);

            foreach (RoadUnit roadUnit in roadUnitMap)
            {
                if (roadUnit.Position.Equals(deletePoint))
                {
                    roadUnitMap.Remove(roadUnit);
                    isRemoved = true;
                    break;
                }
            }
            return isRemoved;
        }

        /// <summary>
        /// Add the road unit to the canvas
        /// </summary>
        /// <param name="roadUnit">The road unit.</param>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        internal void AddRoadUnit(string roadUnit, int x, int y)
        {
            // Formula for getting point position
            int xPosition = (int)(x - (x % (zoom * squareUnit)));
            int yPosition = (int)(y - (y % (zoom * squareUnit)));

            if (roadUnit.Equals("Straight"))
            {
                Straight straight = new Straight(xPosition, yPosition, direction, zoom);
                if (CheckCompatibility(straight))
                {
                    roadUnitMap.Add(straight);
                    ClearStatusLabel();
                }
                else
                {
                    ShowMessageBox("Warning: Compatibility issues");
                }
            }
            else if (roadUnit.Equals("Entrance"))
            {
                Entrance entrance = new Entrance(xPosition, yPosition, direction, zoom);
                if (AddEntrance(entrance))
                {
                   
                    roadUnitMap.Add(entrance);                   
                    ClearStatusLabel();
                   
                }
                else
                {
                    ShowMessageBox("Warning: Compatibility issues");
                }
            }
            else if (roadUnit.Equals("Exit"))
            {
                Exit exit = new Exit(xPosition, yPosition, direction, zoom);
                if (AddExit(exit))
                {
                    
                    roadUnitMap.Add(exit);                   
                    ClearStatusLabel();
                   
                    
                }
                else
                {
                    ShowMessageBox("Warning: Compatibility issues");
                }
            }

            else if (roadUnit.Equals("Bridge"))
            {
                Bridge bridge = new Bridge(xPosition, yPosition, direction, zoom);
                if (CheckCompatibility(bridge))
                {
                    roadUnitMap.Add(bridge);
                    ClearStatusLabel();
                }
                else
                {
                    ShowMessageBox("Warning: Compatibility issues");
                }

            }

        }

        /// <summary>
        /// Adds the exit.
        /// </summary>
        /// <param name="exit">The exit.</param>
        /// <returns></returns>
        private bool AddExit(Exit exit)
        {
            Straight straight = null;
            bool compatible = true;
            foreach (RoadUnit unit in roadUnitMap)
            {
                Point point = new Point(0, 0);
                if (unit.Position != exit.Position)
                {

                    switch (exit.Direction1)
                    {
                        case RoadUnit.Direction.NORTH:
                            point = new Point((int)(exit.Position.X - exit.ImageWidth), (int)(exit.Position.Y - exit.ImageHeight));
                            break;
                        case RoadUnit.Direction.SOUTH:
                            point = new Point(exit.Position.X +(int)unit.ImageWidth, (int)(exit.Position.Y - exit.ImageHeight+unit.ImageHeight));
                            break;
                        case RoadUnit.Direction.WEST:
                            point = new Point(exit.Position.X - (int)exit.ImageWidth, (int)(exit.Position.Y - exit.ImageHeight));
                            break;
                        case RoadUnit.Direction.EAST:
                            point = new Point((int)(exit.Position.X), (int)(exit.Position.Y - exit.ImageHeight));
                            break;
                        default: throw new Exception("Erroro");
                            

                    }
                    if (unit.Direction1 == RoadUnit.Direction.EAST || unit.Direction1 == RoadUnit.Direction.WEST)
                    {
                       /* Console.WriteLine("Here");
                        if (!(CheckEastWestRamps(exit, unit, (int)(zoom * squareUnit))))
                        {
                            compatible = false;


                        }*/
                        if(unit.Position != exit.Position)
                        compatible = CheckRamp(exit,point);
                    }
                    else
                    { /*
                        Console.WriteLine("Here");
                        if (!(CheckNorthSouthRamps(point, unit, (int)(zoom * squareUnit))))
                        {
                            compatible = false;

                        }*/
                        if (unit.Position != exit.Position)
                            compatible = CheckRamp(exit,point);
                    }

                }
                else if (unit is Straight) straight = (Straight)unit;


            }
            if (straight != null && compatible)
            {
                

                if (straight.Direction1 == exit.Direction1)
                {
                    if (exit.Position == straight.Position)
                    {
                        if (straight.LinkedExit == null && straight.LinkedExit == null)
                        {
                            straight.LinkedExit = exit;

                            switch (straight.Direction1)
                            {
                                case RoadUnit.Direction.NORTH:
                                   exit.Position = new Point((int)(exit.Position.X - exit.ImageWidth), (int)(exit.Position.Y - exit.ImageHeight));
                                    break;
                                case RoadUnit.Direction.SOUTH:
                                    exit.Position = new Point(exit.Position.X + (int)straight.ImageWidth, (int)(exit.Position.Y - exit.ImageHeight+straight.ImageHeight));
                                    break;
                                case RoadUnit.Direction.WEST:
                                    exit.Position = new Point(exit.Position.X - (int)exit.ImageWidth, (int)(exit.Position.Y - exit.ImageHeight));
                                    break;
                                case RoadUnit.Direction.EAST:
                                    exit.Position = new Point((int)(exit.Position.X), (int)(exit.Position.Y - exit.ImageHeight));
                                    break;
                                default: throw new Exception("Erroer");
                                    

                            }
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// Adds the entrance to a Straight.
        /// </summary>
        /// <param name="entrance">The entrance.</param>
        /// <returns></returns>
        public bool AddEntrance(Entrance entrance)
        {
            Straight straight = null;
             bool compatible = true;
            foreach (RoadUnit unit in roadUnitMap)
            {
                Point point = new Point(0,0);
                if (unit.Position != entrance.Position)
                {
                   
                    switch (entrance.Direction1)
                    {
                        case RoadUnit.Direction.NORTH:
                            point = new Point((int)(entrance.Position.X - entrance.ImageWidth), entrance.Position.Y);
                            break;
                        case RoadUnit.Direction.SOUTH:
                            point = new Point(entrance.Position.X, (int)(entrance.Position.Y - entrance.ImageHeight));
                            break;
                        case RoadUnit.Direction.WEST:
                            point= new Point(entrance.Position.X, (int)(entrance.Position.Y - entrance.ImageHeight));
                            break;
                        case RoadUnit.Direction.EAST:
                            point = new Point((int)(entrance.Position.X - entrance.ImageWidth + unit.ImageWidth), (int)(entrance.Position.Y - entrance.ImageHeight));
                            break;
                        default: throw new Exception("Erroer");

                            

                    }
                    if (unit.Direction1 == RoadUnit.Direction.EAST || unit.Direction1 == RoadUnit.Direction.WEST)
                    {
                        /*Console.WriteLine("Here");
                        if (!(CheckEastWestRamps(entrance, unit, (int)(zoom * squareUnit))))
                        {
                            compatible = false;

                        }*/
                        if (unit.Position != entrance.Position)
                        compatible = CheckRamp(entrance,point);
                    }
                    else
                    {

                        /*if (!(CheckNorthSouthRamps(point, unit, (int)(zoom * squareUnit))))
                        {
                            compatible = false;

                        }*/
                        if (unit.Position != entrance.Position)
                        compatible = CheckRamp(entrance,point);
                    }

                }
                else if(unit is Straight) straight = (Straight)unit;

               
            }
            if (straight != null && compatible)
            {
               
                if (straight.Direction1 == entrance.Direction1)
                {
                    if (entrance.Position == straight.Position)
                    {
                        if (straight.LinkedExit == null && straight.LinkedExit == null)
                        {
                            straight.LinkedEntrance = entrance;

                            switch (straight.Direction1)
                            {
                                case RoadUnit.Direction.NORTH:
                                    entrance.Position = new Point((int)(entrance.Position.X - entrance.ImageWidth), entrance.Position.Y);
                                    break;
                                case RoadUnit.Direction.SOUTH:
                                    entrance.Position = new Point(entrance.Position.X, (int)(entrance.Position.Y - entrance.ImageHeight));
                                    break;
                                case RoadUnit.Direction.WEST:
                                    entrance.Position = new Point(entrance.Position.X, (int)(entrance.Position.Y - entrance.ImageHeight));
                                    break;
                                case RoadUnit.Direction.EAST:
                                    entrance.Position = new Point((int)(entrance.Position.X - entrance.ImageWidth + straight.ImageWidth), (int)(entrance.Position.Y - entrance.ImageHeight));
                                    break;
                                default: throw new Exception("Erroer");
                                    

                                }
                                return true;
                            }
                        }
                    }
                }
            return false;
        }

        

      
        /// <summary>
        /// Check if unit placement is compatible with the rest of the road units already been placed
        /// This is done by checking the surrounding of the road unit being placed
        /// Entrance/Exit have different checking algorithm because of their size
        /// </summary>
        /// <param name="roadUnit">Road unit to be placed</param>
        /// <returns>Whether it is compatible or not</returns>
        private bool CheckCompatibility(RoadUnit roadUnit)
        {
            bool isCompatible = true;
            int scaledUnit = (int)(zoom * squareUnit);
            foreach (RoadUnit unit in roadUnitMap)
            {
                if (unit.Position.Equals(roadUnit.Position))
                {
                    isCompatible = false;
                    break;
                }
                else
                {
                    Point tempPoint;
                    if ((roadUnit is Straight) || (roadUnit is Bridge))
                    {
                        if (!(unit is Entrance || unit is Exit))
                        {
                            // Check the left side of roadUnit
                            int leftX = roadUnit.Position.X - scaledUnit;
                            tempPoint = new Point(leftX, roadUnit.Position.Y);
                            if (unit.Position.Equals(tempPoint))     // If found
                            {   // If desired road unit is facing NORTH/SOUTH
                                if (roadUnit.Direction1 == RoadUnit.Direction.NORTH || roadUnit.Direction1 == RoadUnit.Direction.SOUTH)
                                {
                                    // Check if Unit is facing EAST/WEST
                                    if (unit.Direction1 == RoadUnit.Direction.EAST || unit.Direction1 == RoadUnit.Direction.WEST)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                }
                                else    // Desired road unit is facing EAST/WEST
                                {
                                    // Check if Unit is facing NORTH/SOUTH
                                    if (unit.Direction1 == RoadUnit.Direction.NORTH || unit.Direction1 == RoadUnit.Direction.SOUTH)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                    // Not in the same direction facing EAST/WEST
                                    else if (roadUnit.Direction1 != unit.Direction1)
                                    {
                                        isCompatible = false;
                                        break;
                                    }

                                }
                            }

                            // Check the right side of the roadUnit
                            int rightX = roadUnit.Position.X + scaledUnit;
                            tempPoint = new Point(rightX, roadUnit.Position.Y);
                            if (unit.Position.Equals(tempPoint))    // If found
                            {
                                // If desired road unit is facing NORTH/SOUTH
                                if (roadUnit.Direction1 == RoadUnit.Direction.NORTH || roadUnit.Direction1 == RoadUnit.Direction.SOUTH)
                                {
                                    // Check if Unit is facing EAST/WEST
                                    if (unit.Direction1 == RoadUnit.Direction.EAST || unit.Direction1 == RoadUnit.Direction.WEST)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                }
                                else    // Desired road unit is facing EAST/WEST
                                {
                                    // Check if Unit is facing NORTH/SOUTH
                                    if (unit.Direction1 == RoadUnit.Direction.NORTH || unit.Direction1 == RoadUnit.Direction.SOUTH)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                    // Not in the same direction facing EAST/WEST
                                    else if (roadUnit.Direction1 != unit.Direction1)
                                    {
                                        isCompatible = false;
                                        break;
                                    }

                                }
                            }

                            // Check the top side of the roadUnit
                            int topY = roadUnit.Position.Y - scaledUnit;
                            tempPoint = new Point(roadUnit.Position.X, topY);
                            if (unit.Position.Equals(tempPoint))    // If found
                            {
                                // If desired road unit is facing NORTH/SOUTH
                                if (roadUnit.Direction1 == RoadUnit.Direction.NORTH || roadUnit.Direction1 == RoadUnit.Direction.SOUTH)
                                {
                                    // Check if Unit is facing EAST/WEST
                                    if (unit.Direction1 == RoadUnit.Direction.EAST || unit.Direction1 == RoadUnit.Direction.WEST)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                    else if (roadUnit.Direction1 != unit.Direction1)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                }
                                else    // Desired road unit is facing EAST/WEST
                                {
                                    // Check if Unit is facing NORTH/SOUTH
                                    if (unit.Direction1 == RoadUnit.Direction.NORTH || unit.Direction1 == RoadUnit.Direction.SOUTH)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                }
                            }


                            // Check the bottom side of the roadUnit
                            int bottomY = roadUnit.Position.Y + scaledUnit;
                            tempPoint = new Point(roadUnit.Position.X, bottomY);
                            if (unit.Position.Equals(tempPoint))    // If found
                            {
                                // If desired road unit is facing NORTH/SOUTH
                                if (roadUnit.Direction1 == RoadUnit.Direction.NORTH || roadUnit.Direction1 == RoadUnit.Direction.SOUTH)
                                {
                                    // Check if Unit is facing EAST/WEST
                                    if (unit.Direction1 == RoadUnit.Direction.EAST || unit.Direction1 == RoadUnit.Direction.WEST)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                    else if (roadUnit.Direction1 != unit.Direction1)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                }
                                else    // Desired road unit is facing EAST/WEST
                                {
                                    // Check if Unit is facing NORTH/SOUTH
                                    if (unit.Direction1 == RoadUnit.Direction.NORTH || unit.Direction1 == RoadUnit.Direction.SOUTH)
                                    {
                                        isCompatible = false;
                                        break;
                                    }
                                }
                            }
                        }
                        else    // Unit checking agains is a entrance/exit
                        {
                            // Got to check it against all the points 4 by 2
                            if (unit.Direction1 == RoadUnit.Direction.NORTH || unit.Direction1 == RoadUnit.Direction.SOUTH)
                            {
                                isCompatible = CheckNorthSouthRamps(unit.Position, roadUnit, scaledUnit);
                                if (!isCompatible)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                isCompatible = CheckEastWestRamps(unit, roadUnit, scaledUnit);
                                if (!isCompatible)
                                {
                                    break;
                                }
                            }
                        }

                    }
                    // If desired road unit is entrance or exit
                    else if ((roadUnit is Entrance) || (roadUnit is Exit))
                    {


                        if (roadUnit.Direction1 == RoadUnit.Direction.NORTH || roadUnit.Direction1 == RoadUnit.Direction.SOUTH)
                        {
                            int originalX = roadUnit.Position.X;
                            int originalY = roadUnit.Position.Y;
                            isCompatible = CheckNorthSouthRamps(roadUnit.Position, unit, scaledUnit);
                            if (!isCompatible)
                                break;
                            if (unit is Entrance || unit is Exit)
                            {
                                isCompatible = CheckNorthSouthRamps(unit.Position, roadUnit, scaledUnit);
                                if (!isCompatible)
                                    break;
                            }

                            if (roadUnit.Direction1 == RoadUnit.Direction.NORTH)
                            {
                                if (roadUnit is Entrance)
                                {
                                    int entranceRoadX = originalX + scaledUnit + scaledUnit;
                                    Point entranceRoadPoint = new Point(entranceRoadX, originalY);
                                    if (unit.Position.Equals(entranceRoadPoint))
                                    {
                                     
                                        if (unit.Direction1 == roadUnit.Direction1)     // Facing same direction
                                        {   // Entrance road found at that position

                                        }
                                        else
                                        {   // Not facing same direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                                else if (roadUnit is Exit)
                                {

                                    int exitRoadX = originalX - scaledUnit;
                                    Point exitRoadPoint = new Point(exitRoadX, originalY);
                                    if (unit.Position.Equals(exitRoadPoint))
                                    {   // Road Unit found at that position
                                        if (unit.Direction1 == RoadUnit.Direction.SOUTH)
                                        {   // Exit road found at that position

                                        }
                                        else
                                        {
                                            // Not facing the appropriate direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }

                                }
                            }
                            else    // Else it's facing SOUTH
                            {
                                if (roadUnit is Entrance)
                                {
                                    int entranceRoadX = originalX - scaledUnit;
                                    int entranceRoadY = originalY + scaledUnit + scaledUnit + scaledUnit;
                                    Point entranceRoadPoint = new Point(entranceRoadX, entranceRoadY);
                                    if (unit.Position.Equals(entranceRoadPoint))
                                    {
                                        
                                        if (unit.Direction1 == roadUnit.Direction1)     // Facing same direction
                                        {   // Entrance road found at that position

                                        }
                                        else
                                        {   // Not facing same direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                                else if (roadUnit is Exit)
                                {
                                    int exitRoadX = originalX + scaledUnit + scaledUnit;
                                    int exitRoadY = originalY + scaledUnit + scaledUnit + scaledUnit;
                                    Point exitRoadPoint = new Point(exitRoadX, exitRoadY);
                                    if (unit.Position.Equals(exitRoadPoint))
                                    {   // Road Unit found at that position
                                        if (unit.Direction1 == RoadUnit.Direction.NORTH)
                                        {   // Exit road found at that position

                                        }
                                        else
                                        {
                                            // Not facing the appropriate direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                            }


                        }
                        else if (roadUnit.Direction1 == RoadUnit.Direction.EAST || roadUnit.Direction1 == RoadUnit.Direction.WEST)
                        {
                            int originalX = roadUnit.Position.X;
                            int originalY = roadUnit.Position.Y;

                            isCompatible = CheckEastWestRamps(roadUnit, unit, scaledUnit);
                            if (!isCompatible)
                                break;

                            if (roadUnit.Direction1 == RoadUnit.Direction.EAST)
                            {   // Facing EAST
                                if (roadUnit is Entrance)
                                {
                                    int entranceRoadX = originalX + scaledUnit + scaledUnit + scaledUnit;
                                    int entranceRoadY = originalY + scaledUnit + scaledUnit;
                                    Point entranceRoadPoint = new Point(entranceRoadX, entranceRoadY);
                                    if (unit.Position.Equals(entranceRoadPoint))
                                    {
                                        
                                        if (unit.Direction1 == roadUnit.Direction1)     // Facing same direction
                                        {   // Entrance road found at that position

                                        }
                                        else
                                        {   // Not facing same direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                                else    // Road Unit is an exit
                                {
                                    int exitRoadX = originalX + scaledUnit + scaledUnit;
                                    int exitRoadY = originalY - scaledUnit - scaledUnit;
                                    Point exitRoadPoint = new Point(exitRoadX, exitRoadY);
                                    if (unit.Position.Equals(exitRoadPoint))
                                    {   // Road Unit found at that position
                                        if (unit.Direction1 == RoadUnit.Direction.WEST)
                                        {   // Exit road found at that position

                                        }
                                        else
                                        {
                                            // Not facing the appropriate direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                            }
                            else    // Road unit facing WEST
                            {
                                if (roadUnit is Entrance)
                                {
                                    int entranceRoadX = originalX;
                                    int entranceRoadY = originalY - scaledUnit;
                                    Point entranceRoadPoint = new Point(entranceRoadX, entranceRoadY);
                                    if (unit.Position.Equals(entranceRoadPoint))
                                    {
                                        
                                        if (unit.Direction1 == roadUnit.Direction1)     // Facing same direction
                                        {   // Entrance road found at that position

                                        }
                                        else
                                        {   // Not facing same direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                                else    // Road Unit is an exit
                                {
                                    int exitRoadX = originalX;
                                    int exitRoadY = originalY + scaledUnit + scaledUnit;
                                    Point exitRoadPoint = new Point(exitRoadX, exitRoadY);
                                    if (unit.Position.Equals(exitRoadPoint))
                                    {   // Road Unit found at that position
                                        if (unit.Direction1 == RoadUnit.Direction.EAST)
                                        {   // Exit road found at that position

                                        }
                                        else
                                        {
                                            // Not facing the appropriate direction
                                            isCompatible = false;
                                            break;
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }

            return isCompatible;
        }


       


      

        /// <summary>
        /// Checking every points on the 2 by 4 road unit if the unit's position is
        /// located in it. Therefore conflict could occur.
        /// </summary>
        /// <param name="roadUnit">Ramp</param>
        /// <param name="unit">Unit compared against</param>
        /// <param name="scaledUnit">Scale of the sqaure unit size</param>
        /// <returns>Returns true if it's compatible</returns>
        private bool CheckNorthSouthRamps(Point roadUnit, RoadUnit unit, int scaledUnit)
        {
            bool isCompatible = true;
            int originalX = roadUnit.X;
            int originalY = roadUnit.Y;
            int rightX = originalX + scaledUnit;
            int bottomY = originalY + scaledUnit;
            int bottom2Y = bottomY + scaledUnit;
            int bottom3Y = bottom2Y + scaledUnit;

            // Create points for multiple area
            Point topRight = new Point(rightX, originalY);
            Point bottom1 = new Point(originalX, bottomY);
            Point bottom1Right = new Point(rightX, bottomY);
            Point bottom2 = new Point(originalX, bottom2Y);
            Point bottom2Right = new Point(rightX, bottom2Y);
            Point bottom3 = new Point(originalX, bottom3Y);
            Point bottom3Right = new Point(rightX, bottom3Y);

            if (unit.Position.Equals(topRight))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom1))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom1Right))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom2))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom2Right))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom3))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom3Right))
            {
                isCompatible = false;
            }

            return isCompatible;
        }
        /// <summary>
        /// Checking every points on the 4 by 2 road unit if the unit's position is
        /// located in it. Therefore conflict could occur.
        /// </summary>
        /// <param name="roadUnit">Ramp</param>
        /// <param name="unit">Road Unit compared against</param>
        /// <param name="scaledUnit">Scale of the sqaure unit size</param>
        /// <returns>Returns true if it's compatible</returns>
        private bool CheckEastWestRamps(RoadUnit roadUnit, RoadUnit unit, int scaledUnit)
        {
            bool isCompatible = true;
            int originalX = roadUnit.Position.X;
            int originalY = roadUnit.Position.Y;
            int rightX = originalX + scaledUnit;
            int right2X = rightX + scaledUnit;
            int right3X = right2X + scaledUnit;
            int bottomY = originalY + scaledUnit;

            Point bottomPoint = new Point(originalX, bottomY);
            Point rightPoint = new Point(rightX, originalY);
            Point bottomRightPoint = new Point(rightX, bottomY);
            Point right2Point = new Point(right2X, originalY);
            Point bottom2Point = new Point(right2X, bottomY);
            Point right3Point = new Point(right3X, originalY);
            Point bottom3Point = new Point(right3X, bottomY);

            if (unit.Position.Equals(bottomPoint))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(rightPoint))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottomRightPoint))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(right2Point))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom2Point))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(right3Point))
            {
                isCompatible = false;
            }
            else if (unit.Position.Equals(bottom3Point))
            {
                isCompatible = false;
            }

            return isCompatible;
        }



        /// <summary>
        /// Checks the ramp to see if there is enought space to place at the current position.
        /// </summary>
        /// <param name="ramp">The ramp.</param>
        /// <returns></returns>
        private bool CheckRamp(RoadUnit ramp, Point rampPoint)
        {

            foreach (RoadUnit roadunit in roadUnitMap)
            {
                if (roadunit.Position.X <= rampPoint.X && roadunit.Position.X + roadunit.ImageWidth > rampPoint.X)
                {
                    if (roadunit.Position.Y <= rampPoint.Y && roadunit.Position.Y + roadunit.ImageHeight < rampPoint.Y)
                    {
                        return false;
                    }
                }
                if (rampPoint.X <= roadunit.Position.X && rampPoint.X + ramp.ImageWidth > roadunit.Position.X)
                {
                    if (roadunit.Position.Y <= rampPoint.Y && roadunit.Position.Y + roadunit.ImageHeight > rampPoint.Y)
                    {
                        return false;
                    }
                }
                if (roadunit.Position.X <= rampPoint.X && roadunit.Position.X + roadunit.ImageWidth > rampPoint.X)
                {
                    if (rampPoint.Y <= roadunit.Position.Y && rampPoint.Y + ramp.ImageHeight > roadunit.Position.Y)
                    {
                        return false;
                    }
                }
                if (rampPoint.X <= roadunit.Position.X && rampPoint.X + ramp.ImageWidth > roadunit.Position.X)
                {
                    if (rampPoint.Y <= roadunit.Position.Y && rampPoint.Y + ramp.ImageHeight > roadunit.Position.Y)
                    {

                        return false;
                    }
                }
            }
            return true;
        }
        /// <summary>
        /// Shows message box popup
        /// </summary>
        /// <param name="message">Message to appear on message box</param>
        private void ShowMessageBox(string message)
        {
            MessageBox.Show(message);
            StatusLabelCallBack(message);
        }

        /// <summary>
        /// Callback function to clear the statuslabel
        /// </summary>
        private void ClearStatusLabel()
        {
            StatusLabelCallBack("");
        }




        /// <summary>
        /// Adds the lanes to sim object.
        /// </summary>
        /// <param name="simObject">The sim object.</param>
        /// <returns></returns>
        public SimObject AddLanesToSimObject(SimObject simObject)
        {
            
            foreach (RoadUnit roadUnit in roadUnitMap)
            {
                // Adds road unit to appropriate linkedlist
                if (!(roadUnit is Entrance || roadUnit is Exit))
                {
                    simObject.AddToLinkedList(roadUnit);
                }
            }
            return simObject;
        }

        /// <summary>
        /// Prepare the design for saving
        /// This is for saving design uses only
        /// </summary>
        /// <returns></returns>
        public List<RoadUnit> GetDesignRoadUnits()
        {
            return roadUnitMap;
        }

        /// <summary>
        /// Method which loads the road unit map
        /// 
        /// </summary>
        /// <param name="roadUnitMap"></param>
        /// <returns>If loads successfully</returns>
        public bool LoadDesign(object roadUnitMap)
        {
            try
            {
                this.roadUnitMap = (List<RoadUnit>)roadUnitMap;
                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return false;
            }
        }

        /// <summary>
        /// Gets the road unit map.
        /// </summary>
        /// <value>The road unit map.</value>
        public List<RoadUnit> RoadUnitMap
        {
            get { return roadUnitMap; }

        }

    }
}